package edu.java.day0801;

/**
 * 线程安全：在并发时保证数据的准确性、效率尽可能高
 * synchronized
 *1.同步方法
 * 2、同步块
 */
public class SynBlockTest03 {
    public static void main(String[] args) {
        //一份资源
        SyneWeb12306 web = new SyneWeb12306();
        //多个代理
        new Thread(web, "zyz").start();
        new Thread(web, "ysm").start();
        new Thread(web, "llk").start();
    }

    static class SyneWeb12306 implements Runnable {
        //票数
        private int ticketNums = 10;
        private boolean flag = true;

        public void run() {
            while (flag) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                test5();
            }
        }
        //尽可能锁定合理范围(不是指代码   指数据的完整性)
        //double checking
        public synchronized void test5() {
            if (ticketNums <= 0) {//考虑的是没有票的情况
                flag = false;
                return;
            }
            synchronized (this) {
                if (ticketNums <= 0) {//考虑最后一张票
                    flag = false;
                    return;
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
            }
        }

        //线程不安全 范围太小锁不住
        public synchronized void test4() {
            synchronized (this) {
                if (ticketNums <= 0) {
                    flag = false;
                    return;
                }
            }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);

        }

        //线程不安全 ticketNums对象在变
        public synchronized void test3() {
            synchronized ((Integer)ticketNums) {
                if (ticketNums <= 0) {
                    flag = false;
                    return;
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
            }
        }
        //线程安全  范围太大-->效率低下
        public synchronized void test2() {
            synchronized (this) {
                if (ticketNums <= 0) {
                    flag = false;
                    return;
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
            }
        }

        //线程安全 同步
        public synchronized void test1() {
            if (ticketNums <=0) {
                flag = false;
                return;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
        }


    }
}
